package framework.provier;

import framework.common.XConfig;
import framework.config.XServiceConfig;
import framework.enums.RpcErrorMessageEnum;
import framework.exception.RpcException;
import framework.registry.Registry;
import framework.registry.ServiceAddress;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
public class ServiceProvider {


    @Autowired
    private Registry registry;

    @Autowired
    private XConfig xConfig;

    private final Map<String, Object> serviceMap;

    public ServiceProvider() {
        serviceMap = new ConcurrentHashMap<>();
    }

    public Object getService(String rpcServiceName) {

        if (serviceMap.containsKey(rpcServiceName)) {
            return serviceMap.get(rpcServiceName);
        }
        throw new RpcException(RpcErrorMessageEnum.SERVICE_CAN_NOT_BE_FOUND);
    }

    private void addService(XServiceConfig serviceConfig) {

        String rpcServiceName = serviceConfig.getRpcServiceName();
        if (serviceMap.containsKey(rpcServiceName)) {
            return;
        }
        serviceMap.put(rpcServiceName, serviceConfig.getService());
        log.debug("add service: [{}] interface: [{}]", rpcServiceName, serviceConfig.getService().getClass().getInterfaces());
    }


    public void publishService(List<XServiceConfig> rpcServiceConfigs) {
        rpcServiceConfigs.forEach(this::publishService);
    }

    public void publishService(XServiceConfig rpcServiceConfig) {

        try {
            String host = InetAddress.getLocalHost().getHostAddress();
            XConfig.Provider provider = xConfig.getProvider();
            if (provider == null) {
                log.debug("none server not publish service");
                return;
            }
            Integer port = provider.getPort();
            addService(rpcServiceConfig);
            registry.serviceRegister(rpcServiceConfig.getRpcServiceName(), new ServiceAddress(host, port));
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }
    }
}
